// noinspection JSUnusedGlobalSymbols

import { Appender } from '../interface/Appender'
import { LoggerLevel } from '../interface/LoggerLevel'
import { HttpRequest, HttpSend } from '../tool/HttpTool'
import { RecorderData } from '../type'

/**
 * HttpRequestRecorder
 *
 * @author 冰凝
 * @date 2022/12/10 21:25
 */
export class HttpRequestAppender implements Appender<HttpRequestRecorderConfig> {
    public config: HttpRequestRecorderConfig
    private readonly _def_size = 10
    private readonly _def_time = 1000_0
    private queue: Array<RecorderData> = new Array<RecorderData>()

    public constructor(config: HttpRequestRecorderConfig) {
        HttpRequestAppender.checkConfig(config)

        this.config = config
        this.initWork()
    }

    private static checkConfig(config: HttpRequestRecorderConfig) {
        const { request, grouping, delay } = config
        if (grouping <= 0) {
            throw new Error('[HttpRequestRecorderConfig] config.grouping 必须大于 0')
        }
        if (delay) {
            throw new Error('[HttpRequestRecorderConfig] config.delay 必须大于 0')
        }
        if (!request.url || !request.method) {
            throw new Error('[HttpRequestRecorderConfig] config.request 无效')
        }
    }

    public append(name: string, level: LoggerLevel, ...args: Array<any>): void {
        this.queue.push({ name, level, msg: args, date: Date.now() })

        // 积累足够数量
        if (this.queue.length >= this.getGroupSize()) {
            this.work()
        }
    }

    private initWork(): void {
        setInterval(() => this.work(), this.getTimeoutSize())
    }

    private work(): void {
        if (this.queue.length <= 0) {
            return
        }
        // 不提前判断 groupSize 退出, 用于日志很少时, 指定 config.delay 至少发送一次
        const group = this.queue.splice(0, this.getGroupSize())
        if (group.length <= 0) {
            return
        }
        const rollback = () => this.queue.unshift(...group)

        try {
            HttpSend({
                ...this.config.request,
                body: JSON.stringify(group),
            })
                .catch(err => {
                    console.error('[HttpRequestRecorder] 同步日志失败: ', err)
                    rollback()
                })
        } catch (e) {
            console.error('[HttpRequestRecorder] 意料之外', e)
            rollback()
        }
    }

    private getTimeoutSize(): number {
        return this.config.delay ?? this._def_time
    }

    private getGroupSize(): number {
        return this.config.grouping ?? this._def_size
    }

}


export interface HttpRequestRecorderConfig {
    /**
     * 请求参数配置
     */
    request: Omit<HttpRequest, 'body'>
    /**
     * 分组发送 <br>
     * 默认每组 10 个;
     */
    grouping: number
    /**
     * 延迟发送, ms; <br>
     * 默认最少 10秒发送一次
     */
    delay: number
}
